from operator import attrgetter
from django.contrib.auth import login, logout, get_user
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import User
from django.views.decorators.csrf import csrf_exempt
from .models import Event, Timetable, Subject, Lesson
from django.shortcuts import redirect, render, HttpResponse, render_to_response
from django.shortcuts import redirect, render, get_object_or_404
from django.core.urlresolvers import reverse
from datetime import datetime, timedelta, date
import re
import calendar
from django.utils.translation import ugettext as _

from django.contrib.auth.decorators import login_required
from models import TimetableForm, SubjectForm, LessonForm,EventForm

import json
from django.core import serializers
from django.template.loader import render_to_string
from django.template import RequestContext, Template

weekDays = ['Mo','Tu','We','Th','Fr','Sa','Su']
weekDaysName= {'Mo': _("Monday"), 'Tu': _("Tuesday"), 'We': _("Wednesday"), 'Th': _("Thursday"), 'Fr': _("Friday"),'Sa': _("Saturday"),'Su': _("Sunday")}

def home(request):
    args = {}
    if(get_user(request)):
        args["loggedIn"] = True
    else:
        args["loggedIn"] = False
    return render(request, "index.html", args)

def overview(request):
    return render(request, "overview.html")


def timetables(request, form = None):
    args = dict()
    months = {1 : _("January"),
             2 : _("February"),
             3 : _("March"),
             4 : _("April"),
             5 : _("May"),
             6 : _("June"),
             7 : _("July"),
             8 : _("August"),
             9 : _("September"),
             10 : _("October"),
             11 : _("November"),
             12 : _("December")}

    now = datetime.now()
    cal = calendar.Calendar()

    weeks = {}
    for timetable in Timetable.objects.filter(user=request.user):
        temp = getWeek(timetable)
        if temp:
            weeks[timetable.id] = temp
    args["weeks"] = weeks
    args["week"] = weekDays
    args["weekDaysName"] = weekDaysName


    timetable_list = Timetable.objects.filter(user=request.user.pk)
    if timetable_list:
        args["timetables"] = timetable_list
    else:
        args["timetables"] = None

    args["cal_"] = cal.monthdayscalendar(now.year, now.month)
    args["cal_current_year"] = now.year
    args["cal_current_month"] = now.month
    args["cal_current_day"] = now.day
    args["cal_current_month_written"] = months[now.month]
    args["cal_current_weekday"] = weekDays[date.today().weekday()]

    if (form == None):
        args["addTimetable_active"] = False
    else:
        args["addTimetable_active"] = True
    args["timetable_form"] = TimetableForm() if form is None else form
    args["subject_form"] = SubjectForm()
    args["lesson_form"] = LessonForm()
    return render(request, "timetables.html", args)

def getWeek(timetable):
    week = []
    for day in weekDays:
        weekDay_tuple = ()
        subject_tuple = ()
        subject_sort = []
        for subject in Subject.objects.filter(timetable_id = timetable.id):
            if not weekDay_tuple:
                weekDay_inner_tuple = (day,)
                weekDay_tuple += (weekDay_inner_tuple,)
            subject_inner_tuple = ()
            lesson_tuple = ()

            for lesson in Lesson.objects.filter(subject_id = subject.id, les_day = day).order_by('les_starttime'):  #Get all Lessons
                if not subject_inner_tuple:
                    subject_inner_tuple += (subject,)
                lesson_tuple += (lesson,)
            if lesson_tuple:
                subject_inner_tuple += (lesson_tuple,)
            if subject_inner_tuple:
                if not subject_sort:
                    subject_sort.append(subject_inner_tuple)
                else:
                    current_starttime = subject_inner_tuple[1][0].les_starttime
                    position = 0
                    for subject in subject_sort:
                        if subject[1][0].les_starttime >= current_starttime:
                            break
                        position += 1
                    subject_sort.insert(position,subject_inner_tuple)
        for subject_inner_tuple in subject_sort:
            subject_tuple += (subject_inner_tuple,)
        if subject_tuple:
            weekDay_tuple += (subject_tuple,)
        if len(weekDay_tuple)>1:
            week.append(weekDay_tuple)
    return week

@login_required
def events(request, form = None):
    args = dict()

    #read from request.Object
    quick = int(request.GET.get('quickfilter',-1))
    args["search_query"] = request.POST.get('search_query','')
    order = request.GET.get('order','20')

    #create datetimes for datefilter and apply quickfilter
    now = datetime.now()

    #quickfilter = all
    if quick==0:
        date_from = datetime(day=1,month=1,year=1900,hour=0,minute=0,second=0)
        date_to = datetime(day=31,month=12,year=2099,hour=23,minute=59,second=59)
    #quickfilter = past
    elif quick==1:
        date_from = datetime(day=1,month=1,year=1900,hour=0,minute=0,second=0)
        date_to = datetime(day=now.day,month=now.month,year=now.year,hour=now.hour,minute=now.minute,second=now.second-1)
    #quickfilter = upcomming
    elif quick==2:
        date_from = datetime(day=now.day,month=now.month,year=now.year,hour=now.hour,minute=now.minute,second=now.second)
        date_to = datetime(day=31,month=12,year=2099,hour=23,minute=59,second=59)
    #quickfilter = today
    elif quick==3:
        date_from = datetime(day=now.day,month=now.month,year=now.year,hour=0,minute=0,second=0)
        date_to = datetime(day=now.day,month=now.month,year=now.year,hour=23,minute=59,second=59)
    #quickfilter = week
    elif quick==4:
        date_from = now - timedelta(days = now.weekday())
        date_from = datetime(day=date_from.day,month=date_from.month,year=date_from.year,hour=0,minute=0,second=0)
        date_to = now + timedelta(days = 6-now.weekday())
        date_to = datetime(day=date_to.day,month=date_to.month,year=date_to.year,hour=23,minute=59,second=59)
    #quickfilter = month
    elif quick==5:
        date_from = datetime(day=1,month=now.month,year=now.year,hour=0,minute=0,second=0)
        date_to = datetime(day=31,month=now.month,year=now.year,hour=23,minute=59,second=59)
    #quickfilter = year
    elif quick==6:
        date_from = datetime(day=1,month=1,year=now.year,hour=0,minute=0,second=0)
        date_to = datetime(day=31,month=12,year=now.year,hour=23,minute=59,second=59)
    #quickfilter = none
    else:
        args["date_from_day"] = int(request.POST.get('date_from_day',now.day))
        args["date_from_month"] = int(request.POST.get('date_from_month',now.month))
        args["date_from_year"] = int(request.POST.get('date_from_year',now.year))
        args["date_to_day"] = int(request.POST.get('date_to_day',31))
        args["date_to_month"] = int(request.POST.get('date_to_month',12))
        args["date_to_year"] = int(request.POST.get('date_to_year',2099))
        date_from = datetime(day=args["date_from_day"],month=args["date_from_month"],year=args["date_from_year"],hour=0,minute=0,second=0)
        date_to = datetime(day=args["date_to_day"],month=args["date_to_month"],year=args["date_to_year"],hour=23,minute=59,second=59)

    args["date_from_day"] = date_from.day
    args["date_from_month"] = date_from.month
    args["date_from_year"] = date_from.year
    args["date_to_day"] = date_to.day
    args["date_to_month"] = date_to.month
    args["date_to_year"] = date_to.year


    #set help variables for template
    args["days"] = range(1,32)
    args["months"] = range(1,13)
    args["years"] = range(1900,2100)

    event_list = Event.objects.filter(user=request.user.pk)

    #apply datefilter
    event_list = event_list.filter(ev_startdate__range=[date_from, date_to])

    #filter by searchpattern
    if(args["search_query"] != ''):
        event_list = event_list.filter(ev_name__icontains=args["search_query"]) | \
                     event_list.filter(ev_description__icontains=args["search_query"]) | \
                     event_list.filter(ev_starttime__icontains=args["search_query"]) | \
                     event_list.filter(ev_endtime__icontains=args["search_query"]) | \
                     event_list.filter(ev_startdate__icontains=args["search_query"]) | \
                     event_list.filter(ev_enddate__icontains=args["search_query"]) | \
                     event_list.filter(ev_location__icontains=args["search_query"]) | \
                     event_list.filter(ev_color__icontains=args["search_query"])


    #Orders: XX
    # first number = column number - second number 0/1 = ascending/descending -> 21 = second column, descending
    if order == '10':
        event_list = sorted(event_list, key=attrgetter('ev_name','ev_startdate','ev_enddate','ev_starttime','ev_endtime'), reverse=False)
    elif order == '11':
        event_list = sorted(event_list, key=attrgetter('ev_name','ev_startdate','ev_enddate','ev_starttime','ev_endtime'), reverse=True)
    elif order == '20':
        event_list = sorted(event_list, key=attrgetter('ev_startdate','ev_enddate','ev_starttime','ev_endtime','ev_name'), reverse=False)
    elif order == '21':
        event_list = sorted(event_list, key=attrgetter('ev_startdate','ev_enddate','ev_starttime','ev_endtime','ev_name'), reverse=True)
    elif order == '30':
        event_list = sorted(event_list, key=attrgetter('ev_starttime','ev_endtime','ev_startdate','ev_enddate','ev_name'), reverse=False)
    elif order == '31':
        event_list = sorted(event_list, key=attrgetter('ev_starttime','ev_endtime','ev_startdate','ev_enddate','ev_name'), reverse=True)
    else:
        event_list = sorted(event_list, key=attrgetter('ev_startdate','ev_enddate','ev_starttime','ev_endtime','ev_name'), reverse=False)

    #set event_list for template
    args["events"] = event_list

    #create form to add event
    form = EventForm()
    args["form"] = form

    return render(request, "events.html", args)

def settings(request):
    args = dict()
    user = get_user(request)
    mailhidden = request.POST.get('mailhidden',-1)
    namehidden = request.POST.get('namehidden',-1)

    if mailhidden != -1:
        user.email = request.POST.__getitem__('email')
    if namehidden != -1:
        user.username = request.POST.__getitem__('username')

    user.save()
    args['email'] = user.email
    args['username'] = user.username
    return render(request, "settings.html", args)

def userlogin(request):
    args = dict()

    if request.method == 'POST':
        form = AuthenticationForm(data=request.POST)

        if form.is_valid():
            if form.get_user().is_active:
                login(request, form.get_user())
                return redirect(reverse("donutscheduler.views.timetables"))
    else:
        form = AuthenticationForm()

    args["form"] = form
    return render(request, "login.html", args)

def register(request):
    args = dict()

    if request.method == 'POST':
        form = UserCreationForm(data=request.POST)

        if form.is_valid():
            new_user = form.save()
            #autologin after registration
            new_user.backend = "django.contrib.auth.backends.ModelBackend"
            login(request, new_user)
            return redirect(reverse("donutscheduler.views.overview"))

    else:
        form = UserCreationForm()

    args["form"] = form
    return render(request, "register.html", args)


def userlogout(request):
    logout(request)
    return render(request, "index.html")

@login_required
def addTimetable(request):
    if request.method == 'POST':
        form = TimetableForm(data=request.POST)
        if form.is_valid():
            new_timetable = form.save(commit=False)
            new_timetable.user = request.user
            new_timetable.save()
            return redirect('donutscheduler.views.timetables')
        else:
            return timetables(request, form)
    else:
        form = TimetableForm()
    return form

@login_required
def deleteEvent(request):
    id = request.GET['id']

    try:
        event = Event.objects.get(pk = id)
    except:
        return redirect('donutscheduler.views.events')
    else:
        event.delete()
        return redirect('donutscheduler.views.events')

@login_required
def deleteTimetable(request):
    id = request.GET['id']

    timetable = Timetable.objects.get(pk = id)
    timetable.delete()
    return redirect('donutscheduler.views.timetables')

@login_required
def addSubject(request):
    if request.method == 'POST':
        form = SubjectForm(data=request.POST)
        if form.is_valid():
            new_subject = form.save(commit=False)
            new_subject.timetable = Timetable.objects.get(pk=request.POST.__getitem__('timetable'))
            new_subject.save()
            return redirect('donutscheduler.views.overview')
    else:
        form = SubjectForm()
    return render(request, 'addSubject.html',
        {'form': form, })


@login_required
def addLesson(request):
    if request.method == 'POST':
        form = LessonForm(data=request.POST)
        if form.is_valid():
            new_lesson = form.save(commit=False)
            new_lesson.subject =  Subject.objects.get(pk=request.POST.__getitem__('subject'))
            new_lesson.save()
            return redirect('donutscheduler.views.overview')
    else:
        form = LessonForm()
    return render(request, 'addLesson.html',
        {'form': form, })

@login_required
def deleteLesson(request):
    id = request.GET['id']

    lesson = Lesson.objects.get(pk = id)
    lesson.delete()
    return redirect('donutscheduler.views.timetables')


@login_required
def addSubjectLesson(request):
    if request.method == 'POST':
        subject_form = SubjectForm(data=request.POST)
        if subject_form.is_valid():
            new_subject = subject_form.save(commit=False)
            new_subject.timetable = Timetable.objects.get(pk=request.POST.__getitem__('timetable'))
            new_subject.save()
            lesson_form = LessonForm(data=request.POST)
            if lesson_form.is_valid():
                new_lesson = lesson_form.save(commit=False)
                new_lesson.subject = new_subject
                print request.POST.__getitem__('les_day')
                new_lesson.les_day = request.POST.__getitem__('les_day')
                new_lesson.save()
                return redirect('donutscheduler.views.timetables')
            else:
                return timetables(request, lesson_form) #Muss noch in der timetable behandelt werden
        else:
            return timetables(request, subject_form)    #Muss noch...
    else:
        return timetables(request)

@login_required
def addSL(request):
    if request.method == 'POST' and request.is_ajax():
        lesson_form = LessonForm(request.POST)
        current_timetable = Timetable.objects.get(pk=request.POST.__getitem__('timetable'))

        #check if new Subject already exist to keep the db consistent
        current_subject = Subject.objects.filter(sub_professor = request.POST.get('sub_professor'), sub_name = request.POST.get('sub_name'), sub_color = request.POST.get('sub_color'))
        if current_subject:
            current_subject = current_subject[0]

        if request.POST.has_key('professorChoice') and request.POST.has_key('subjectChoice') or current_subject:
            if not current_subject:
                current_subject = Subject.objects.filter(sub_professor = request.POST.get('professorChoice'), sub_name = request.POST.get('subjectChoice'))[0]
            if lesson_form.is_valid() and current_subject:
                new_lesson = lesson_form.save(commit=False)
                new_lesson.subject = current_subject
                new_lesson.les_day = request.POST.__getitem__('les_day')
                new_lesson.save()
                return HttpResponse(json.dumps({'success':'True'}), mimetype="application/json")
            else:
                template = "addSubjectLesson.html"
                html = render_to_string(template, RequestContext(request,{'subject_form': SubjectForm(), 'lesson_form': lesson_form, 'timetable': current_timetable}))
                return HttpResponse(json.dumps({'success':'False', 'html':html, 'choice': 'True'}), mimetype="application/json")
        else:
            subject_form = SubjectForm(request.POST)
            if subject_form.is_valid():
                if lesson_form.is_valid():
                    new_subject = subject_form.save(commit=False)
                    new_subject.timetable = current_timetable
                    new_subject.save()
                    new_lesson = lesson_form.save(commit=False)
                    new_lesson.subject = new_subject
                    new_lesson.les_day = request.POST.__getitem__('les_day')
                    new_lesson.save()
                    return HttpResponse(json.dumps({'success':'True'}), mimetype="application/json")
                else:
                    template = "addSubjectLesson.html"
                    html = render_to_string(template, RequestContext(request,{'subject_form': subject_form, 'lesson_form': lesson_form, 'timetable': current_timetable}))
                    return HttpResponse(json.dumps({'success':'False', 'html':html, 'choice': 'False'}), mimetype="application/json")
            else:
                lesson_form.is_valid()
                template = "addSubjectLesson.html"
                html = render_to_string(template, RequestContext(request, {'subject_form': subject_form, 'lesson_form': lesson_form, 'timetable': current_timetable}))
                return HttpResponse(json.dumps({'success':'False', 'html':html, 'choice': 'False'}), mimetype="application/json")
    return HttpResponse(json.dumps({'success':'True'}), mimetype="application/json")


def getProfessor(request, timetableId):
    if request.user.is_authenticated():
        data = [{"optionValue": 0, "optionDisplay": _('professor...')},]
        temp = []
        for subject in Subject.objects.filter(timetable_id = timetableId):
            if subject.sub_professor not in temp:
                data.append({"optionValue": subject.id, "optionDisplay": subject.sub_professor})
                temp.append(subject.sub_professor)
    else:
        return redirect('home')
    return HttpResponse(json.dumps(data), mimetype="application/json")

def getSubject(request, timetableId, professor):
    if request.user.is_authenticated():
        data = []
        for subject in Subject.objects.filter(timetable_id = timetableId, sub_professor = professor):
            data.append({"optionValue": subject.id, "optionDisplay": subject.sub_name})
    else:
        return redirect('home')
    return HttpResponse(json.dumps(data), mimetype="application/json")

def addEvent(request):
    if request.method == 'POST':

        form = EventForm(data=request.POST)

        if form.is_valid():
            new_event = form.save(commit=False)
            new_event.user = request.user
            new_event.ev_name[0].upper()
            new_event.ev_name = new_event.ev_name
            new_event.save()
            return redirect('donutscheduler.views.events')
    else:
        form = EventForm()
    return render(request, 'events.html', {'form': form, })

def impressum(request):
    return render(request, 'impressum.html')
